package at.irian.jsfatwork.broker.web.model;

import at.irian.jsfatwork.broker.domain.order.Order;
import at.irian.jsfatwork.broker.domain.order.OrderType;
import at.irian.jsfatwork.broker.domain.order.Ordering;
import at.irian.jsfatwork.broker.domain.stock.Quote;
import at.irian.jsfatwork.broker.domain.stock.Stock;
import at.irian.jsfatwork.broker.domain.stock.StockExchange;
import org.apache.myfaces.orchestra.conversation.Conversation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import java.util.List;

/**
 * @author Thomas Spiegl
 */
@Component
@Scope("conversation.manual")
public class OrderBean {

    private String stockSymbol;

    private Quote quote;

    private Order order;

    private OrderType orderType;

    @Autowired
    private ClientBean clientBean;

    @Autowired
    private StockExchange stockExchange;

    @Autowired
    private Ordering ordering;

    // ----------------------------- Bindings

    public String getStockSymbol() {
        return stockSymbol;
    }

    public List<Stock> autocomplete(Object suggest) {
        return stockExchange.findStocks(suggest.toString());
    }

    public void setStockSymbol(String stockSymbol) {
        this.stockSymbol = stockSymbol;
    }

    public Order getOrder() {
        if (order == null) {
            throw new RuntimeException("Order must not be null, lookup stock symbol before");
        }
        return order;
    }

    public Quote getQuote() {
        return quote;
    }

    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }

    // ----------------------------- Actions

    public String buy() {
        this.orderType = OrderType.BUY;
        return findStock();
    }

    public String sell() {
        this.orderType = OrderType.SELL;
        return findStock();
    }

    private String findStock() {
        if (orderType ==null) {
            throw new RuntimeException("order type must be set before findStock");
        }
        order = null;
        Stock stock = stockExchange.findStockBySymbol(stockSymbol);
        if (stock == null) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Stock (" + stockSymbol + ") not found."));
            return null;
        } else {
            quote = stockExchange.getQuote(stock);
            if (quote == null) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("No Quote for Stock (" + stockSymbol + ") found."));
                return null;
            } else {
                order = ordering.createNewOrder(clientBean.getClient(), orderType, stock);
                return "orderDetails";
            }
        }
    }

    @Transactional
    public String sendOrder() {
        if (orderType ==null) {
            throw new RuntimeException("order must be set before sendOrder");
        }
        ordering.sendAndExecuteOrder(order);
        if (order.isComplete()) {
            Conversation.getCurrentInstance().invalidate();
            return "orderComplete";
        } else {
            Conversation.getCurrentInstance().invalidate();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Order has been sent (status=" +
                    order.getOrderStatus().name() + ")"));
            return "orderPending";
        }

    }

}
